package reference.vo;

import lombok.Data;
import reference.RefUtils;
import reference.constant.RefConstant;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author hujian
 * @date 2023/2/17 9:50
 * @description
 */
@Data
public class ReferenceVo {

    /**
     * 源文本
     */
    private String sourceText;

    /**
     * 修正后的格式
     */
    private String formatText;

    private List<String> authorList = new ArrayList<>();

    private List<String> translatorList = new ArrayList<>();

    private String authors;

    private String title;

    private String type;

    private String location;

    private String school;

    private String year;

    private String volumePeriod;

    private String page;

    private String other;

    private Map<String, ComponentVo> componentVoMap = new HashMap<>();


    /**
     * 是否规范
     */
    private boolean isNorm;

    private String language;

    private List<String> errorMsg = new ArrayList<>();
    private List<String> errorMsgSummary = new ArrayList<>();

    public void generateComponent(String name, String text) {
        ComponentVo vo = new ComponentVo(name);
        int i = sourceText.indexOf(text);
        if (i != -1) {
            vo.setStart(i);
            vo.setEnd(i + text.length());
            vo.setText(text);
            componentVoMap.put(name, vo);
        }
    }

    /**
     * 生成错误总结
     */
    public void generateSummary(int index) {
        StringBuilder formatContent = new StringBuilder();

        //遍历作者,标题,机构,年份,页码, 以及中间的部分
        if (componentVoMap.containsKey(RefConstant.REF_AUTHOR)) {
            // 1、校验作者前面的内容
            ComponentVo componentVo = componentVoMap.get(RefConstant.REF_AUTHOR);
            Integer start = componentVo.getStart();
            String beforeSymbol = sourceText.substring(0, start);
            componentVo.setBeforeSymbol(beforeSymbol);
            //检查序号
            checkIndex(beforeSymbol, formatContent, index);
            //检查作者
            checkAuthor(beforeSymbol, formatContent);

        } else if (authorList.size() > 0) {
            //TODO 这里需要截取到在原文中的位置进一步判断是否有问题
            formatContent.append(String.join("，", authorList)).append(".");
        }

        if (null == title) {
            errorMsgSummary.add("缺失题目信息,建议补充");
        } else if (componentVoMap.containsKey(RefConstant.REF_TITLE)) {
            ComponentVo componentVo = componentVoMap.get(RefConstant.REF_TITLE);
            Integer start = componentVo.getStart();
            if (componentVoMap.containsKey(RefConstant.REF_AUTHOR)) {
                //2、校验题目和作者之间的信息
                String beforeSymbol = sourceText.substring(componentVoMap.get(RefConstant.REF_AUTHOR).getEnd(), start);
                componentVo.setBeforeSymbol(beforeSymbol);
                if (language.equals(RefConstant.REF_CN) && !beforeSymbol.equals(".")) {
                    errorMsgSummary.add("作者和标题之间应该以点号连接");
                } else if (language.equals(RefConstant.REF_EN) && !beforeSymbol.contains(" ")) {
                    errorMsgSummary.add("作者和标题之间应该以点号空格连接");
                }

            } else {
                //没有作者的时候需要先检查拼接序号
                String beforeText = sourceText.substring(0, start);
                checkIndex(beforeText, formatContent, index);
            }
            //拼接题目信息
            if (null != title) {
                if (language.equals(RefConstant.REF_CN)) {
                    formatContent.append(title);
                } else {
                    formatContent.append(" ").append(title);
                }
            }
        }

        if (componentVoMap.containsKey(RefConstant.REF_TYPE)) {
            ComponentVo componentVo = componentVoMap.get(RefConstant.REF_TYPE);
            Integer start = componentVo.getStart();
            if (componentVoMap.containsKey(RefConstant.REF_TITLE)) {
                //2、校验类型和题目之间的信息
                String beforeSymbol = sourceText.substring(componentVoMap.get(RefConstant.REF_TITLE).getEnd(), start);
                componentVo.setBeforeSymbol(beforeSymbol);
                if (beforeSymbol.length() > 0) {
                    errorMsgSummary.add("类型和题目之间应该直接连接不包含其他内容");
                }
            }
            //拼接类型信息
            checkType(formatContent);
        } else {
            checkType(formatContent);
        }

        if (null == school) {
            errorMsgSummary.add("缺失机构信息,建议补充");
        } else if (componentVoMap.containsKey(RefConstant.REF_SCHOOL)) {
            ComponentVo componentVo = componentVoMap.get(RefConstant.REF_SCHOOL);
            ComponentVo componentVo1 = componentVoMap.get(RefConstant.REF_LOCATION);
            if (componentVoMap.containsKey(RefConstant.REF_LOCATION) && componentVo1.getStart() > 0) {
                componentVo = componentVo1;
            }
            Integer start = componentVo.getStart();
            if (componentVoMap.containsKey(RefConstant.REF_TYPE)) {
                //2、校验机构和类型之间的信息
                String beforeSymbol = sourceText.substring(componentVoMap.get(RefConstant.REF_TYPE).getEnd(), start);
                componentVo.setBeforeSymbol(beforeSymbol);
                if (language.equals(RefConstant.REF_CN) && !beforeSymbol.equals(".")) {
                    errorMsgSummary.add("机构和类型之间应该以点号连接");
                } else if (language.equals(RefConstant.REF_EN) && beforeSymbol.length() > 1) {
                    errorMsgSummary.add("机构和类型之间应该以点号直接连接");
                }
            }
            //拼接机构信息
            if (null != school) {
                formatContent.append(school);
            }
        }
        int end = 0;
        if (null == year) {
            errorMsgSummary.add("缺失年份信息,建议补充");
        } else if (componentVoMap.containsKey(RefConstant.REF_YEAR)) {
            ComponentVo componentVo = componentVoMap.get(RefConstant.REF_YEAR);
            end = componentVo.getEnd();
            Integer start = componentVo.getStart();
            if (componentVoMap.containsKey(RefConstant.REF_SCHOOL)) {
                //2、校验年份和机构之间的信息
                String beforeSymbol = sourceText.substring(componentVoMap.get(RefConstant.REF_SCHOOL).getEnd(), start);
                componentVo.setBeforeSymbol(beforeSymbol);
                if (language.equals(RefConstant.REF_EN) && !beforeSymbol.equals(",")) {
                    errorMsgSummary.add("年份和机构之间应该以英文逗号连接");
                }
            }
            formatContent.append(",").append(year);
        }

        if (null == page) {
            errorMsgSummary.add("缺失页码信息");
        } else if (componentVoMap.containsKey(RefConstant.REF_PAGE)) {
            ComponentVo componentVo = componentVoMap.get(RefConstant.REF_PAGE);
            end = componentVo.getEnd();
            Integer start = componentVo.getStart();
            if (componentVoMap.containsKey(RefConstant.REF_YEAR)) {
                //2、校验页码和年份之间的信息
                String beforeSymbol = sourceText.substring(componentVoMap.get(RefConstant.REF_YEAR).getEnd(), start);
                componentVo.setBeforeSymbol(beforeSymbol);
                if (RefUtils.hasDBC(beforeSymbol)) {
                    beforeSymbol = RefUtils.toDBC(beforeSymbol);
                    errorMsgSummary.add("页码信息前应该使用半角符号");
                }
                formatContent.append(beforeSymbol).append(page).append(".");
            }
        }
        if (end > 0) {
            //可能后面有遗漏则再补充回来
            String endText = sourceText.substring(end);
            if (endText.trim().startsWith(".")) {
                formatContent.append(endText.trim().substring(1));
            } else {
                formatContent.append(endText);
            }
        }
        formatText = formatContent.toString();
    }


    /**
     * 检查参考文献前面的序号
     *
     * @param beforeSymbol  text
     * @param formatContent 校正后的格式问题
     * @param index         索引位置
     */
    private void checkIndex(String beforeSymbol, StringBuilder formatContent, int index) {
        String seq = RefUtils.findPattern(beforeSymbol, "\\[(?<seq>\\d+)\\]");
        if (null == seq) {
            String num = RefUtils.findPattern(beforeSymbol, "\\d+");
            if (null != num) {
                formatContent.append("[").append(num).append("]");
            } else {
                formatContent.append("[").append(index).append("]");
            }
            errorMsgSummary.add("作者前面的序号不符合国标规范");
        } else {
            formatContent.append(seq);
        }
    }

    private void checkAuthor(String beforeSymbol, StringBuilder formatContent) {
        //作者 后校验
        if (authorList.size() == 0) {
            //根据规则识别得到作者列表
            if (null != authors) {
                if (language.equals(RefConstant.REF_CN)) {
                    List<ComponentVo> componentVos = RefUtils.getComponentVo(authors);
                    for (ComponentVo componentVo : componentVos) {
                        if (componentVo.getText().length() > 1) {
                            authorList.add(componentVo.getText());
                        }
                    }
                    if (authorList.size() > 3) {
                        formatContent.append(String.join("，", authorList.subList(0, 3)));
                        if (!authors.endsWith("等")) {
                            errorMsgSummary.add("多个作者取前三个姓名以等结尾");
                        }
                        formatContent.append("等.");
                    } else {
                        formatContent.append(String.join(",", authorList)).append(".");
                    }

                    if (beforeSymbol.contains(" ") || authors.startsWith(" ")) {
                        errorMsgSummary.add("作者前面应该不包含空格");
                    } else if (authors.trim().contains(" ")) {
                        errorMsgSummary.add("作者中间应该不包含空格");
                    }
                    if (authors.contains("，")) {
                        errorMsgSummary.add("作者中间应该以英文逗号分隔");
                    }
                } else {
                    //英文作者
                    formatContent.append(authors);
                }
            } else {
                errorMsgSummary.add("缺失作者信息,建议补充");
            }
        } else {
            //TODO 这里需要截取到在原文中的位置进一步判断是否有问题
            formatContent.append(String.join("，", authorList)).append(".");
        }
    }

    private void checkType(StringBuilder formatContent) {
        if (null != type) {
            if (RefUtils.matchPattern(type, "\\[[A-Z]\\]")) {
                formatContent.append(type).append(".");
            } else {
                String enTxt = RefUtils.getEnTxt(type);
                if (enTxt.length() == 1) {
                    errorMsgSummary.add("类型信息不规范,请以英文中括号标注");
                    formatContent.append("[").append(enTxt).append("]").append(".");
                } else {
                    errorMsgSummary.add("类型信息不规范,非电子文献类信息请使用一个大小字母表示");
                }
            }
        } else {
            formatContent.append(".");
            errorMsgSummary.add("缺失类型信息,建议补充");
        }
    }

}
